package com.changgou.seckill.task;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import entity.IdWorker;
import entity.SeckillStatus;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MultiThreadingCreateOrder {
    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    /**
     * 多线程下单
     */
    @Async
    public void createOrder(){
        try {
            //将秒杀抢单信息存入到Redis中,这里采用List方式存储,List本身是一个队列
            SeckillStatus seckillStatus =(SeckillStatus)  redisTemplate.boundListOps("SeckillOrderQueue").rightPop();
            if (seckillStatus == null ){
                return;
            }
            //获取想要资料
            //时间区间
            String time = seckillStatus.getTime();
            //用户登录名
            String username=seckillStatus.getUsername();
            //用户抢购商品
            Long id = seckillStatus.getGoodsId();
            //先查询库存
            //"SeckillGoodsCountList_"+seckillGood.getId()
            Object sgoods = redisTemplate.boundListOps("SeckillGoodsCountList_"+id).rightPop();
            if (sgoods == null){
                clearUserQueue(username);
                return;
            }

            //创建订单对象存入redis
            SeckillOrder seckillOrder = new SeckillOrder();
            String key = "SeckillGoods_" + time;

            SeckillGoods seckillGoods =(SeckillGoods) redisTemplate.boundHashOps(key).get(id);
            //判断库存
            if (seckillGoods == null || seckillGoods.getStockCount()<=0){
                throw new RuntimeException("已售完");
            }
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id);
            seckillOrder.setMoney(seckillGoods.getCostPrice());
            seckillOrder.setUserId(username);
            seckillOrder.setCreateTime(new Date());
            seckillOrder.setStatus("0");//未支付
        /*
            单用户只允许一个未支付订单
            订单在redis中操作
         */
            redisTemplate.boundHashOps("SeckillOrder").put(username,seckillOrder);
            //减少库存
//            seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
            //商品库存-1
            Long surplusCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(id, -1);//商品数量递减
            seckillGoods.setStockCount(surplusCount.intValue());    //根据计数器统计
            //获得队列数量
            Long size = redisTemplate.boundListOps("SeckillGoodsCountList_" + id).size();
            //判断当前商品是否还有库存
//            if(seckillGoods.getStockCount()<=0){
            if(size <=0){
                //并且将商品数据同步到MySQL中
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);
                //如果没有库存,则清空Redis缓存中该商品
                redisTemplate.boundHashOps("SeckillGoods_" + time).delete(id);
            }else{
                //如果有库存，则直数据重置到Reids中
                redisTemplate.boundHashOps("SeckillGoods_" + time).put(id,seckillGoods);
            }
            //更新下单状态
            //抢单成功，更新抢单状态,排队->等待支付
            seckillStatus.setStatus(2);
            seckillStatus.setOrderId(seckillOrder.getId());
            seckillStatus.setMoney(Float.valueOf(seckillGoods.getCostPrice()));
            redisTemplate.boundHashOps("UserQueueStatus").put(username,seckillStatus);

            //发送消息给延时队列
            rabbitTemplate.convertAndSend("delaySeckillQueue", (Object) JSON.toJSONString(seckillStatus), new MessagePostProcessor() {
                @Override
                public Message postProcessMessage(Message message) throws AmqpException {
                    //延时10s
                    message.getMessageProperties().setExpiration("10000");
                    return message;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清理用户排队信息
     */
    public void clearUserQueue(String username){
        //清理排队标识(用于判断是否重复抢单)
        redisTemplate.boundHashOps("UserQueueCount").delete(username);
        //清理抢单状态
        redisTemplate.boundHashOps("UserQueueStatus").delete(username);
    }
}
